package com.appkubes.fintech.admin.application.credit.service.impl;

import com.appkubes.fintech.admin.application.credit.dao.CreditDao;
import com.appkubes.fintech.admin.application.credit.service.CreditService;
import com.appkubes.fintech.admin.application.order.dao.RentOrderDao;
import com.appkubes.fintech.admin.application.user.entity.vo.UserApprovalVO;
import com.appkubes.fintech.common.exption.BusinessException;
import com.appkubes.fintech.common.response.Response;
import com.appkubes.fintech.core.po.FintechCredit;
import com.appkubes.fintech.core.po.FintechCreditExample;
import com.appkubes.fintech.core.po.FintechRentOrder;
import com.appkubes.fintech.core.po.FintechRentOrderExample;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @Author: Rongjie
 * @Date: 2020/01/05
 * @Description:
 */

@Service
@Slf4j
@Data
public class CreditServiceImpl implements CreditService {

    @Resource
    CreditDao creditDao;


    @Resource
    private RentOrderDao orderRepository;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private final static String REDIS_OPERATE_ORDER_LOCK_KEY_PREFIX = "kylin_fintech:operate_order_lock:";
    private final static String REDIS_OPERATE_RESTORE_LIMIT_LOCK_KEY_PREFIX = "kylin_fintech:operate_restore_limit_lock:";
    private final static String REDIS_OPERATE_DEDUCE_LIMIT_LOCK_KEY_PREFIX = "kylin_fintech:operate_credit_limit_lock:";


    /**
     * 获取用户信用额度
     *
     * @param userKey
     * @return
     */
    @Override
    public FintechCredit getCredit(String userKey) {
        FintechCredit credit = creditDao.selectByPrimaryKey(userKey);
        if (credit == null) {
            credit = new FintechCredit();
            credit.setUserKey(userKey);
            creditDao.insertSelective(credit);
            credit = creditDao.selectByPrimaryKey(userKey);//更新数据库默认值
        }
        return credit;
    }

    @Override
    public Response<FintechCredit> initCredit(String userKey, Integer amt) {

        return Response.success();
    }

    @Override
    public FintechCredit addCredit(String userKey, Long creditAmount) throws BusinessException {
        String key = REDIS_OPERATE_DEDUCE_LIMIT_LOCK_KEY_PREFIX + userKey;
        Boolean lockKeyFlag = stringRedisTemplate.hasKey(key);
        if (lockKeyFlag != null && lockKeyFlag) {
            throw new BusinessException("正在扣除额度，请稍后！");
        }
        //加锁
        stringRedisTemplate.opsForValue().set(key, "1", 10, TimeUnit.SECONDS);
        try {
            FintechCredit credit = getCredit(userKey);


            long newCredit = credit.getCreditAmount() + (creditAmount);
            if (creditAmount > 0) {
                credit.setCreditAmount(newCredit);
            } else {
                //扣额度
                long restCredit = credit.getCreditAmount() - credit.getFreezeAmount() + (creditAmount);
                if (restCredit < 0) {
                    throw new BusinessException("该用户额度不足，请选择其他商品！");
                }
                credit.setFreezeAmount(credit.getFreezeAmount() - (creditAmount));
            }
            credit.setUpdateTime(new Date());
            creditDao.updateByPrimaryKeySelective(credit);
            return credit;
        } finally {
            //解锁
            stringRedisTemplate.delete(key);
        }
    }

    @Override
    @Transactional
    public Response<FintechCredit> frozenCredit(String userKey, Integer amt) {
        FintechCredit credit = getByUserKey(userKey);
        if (credit.getForzenAmount() == null) {
            credit.setForzenAmount(0L);
        }
        Long surAmt = credit.getCreditAmount() - credit.getFreezeAmount() - credit.getForzenAmount();
        if (surAmt < amt) {
            return Response.fail("额度不足，冻结失败");
        }
        credit.setForzenAmount(credit.getForzenAmount() + amt);
        credit.setUpdateTime(new Date());
        creditDao.updateByPrimaryKey(credit);
        return Response.success(credit);
    }

    @Override
    @Transactional
    public Response<FintechCredit> unfrozenCredit(String userKey, Integer amt) {
        FintechCredit credit = getByUserKey(userKey);
        if (credit.getForzenAmount() == null) {
            credit.setForzenAmount(0L);
        }
        if (credit.getForzenAmount() < amt) {
            return Response.fail("解冻失败，额度不足");
        }
        credit.setForzenAmount(credit.getForzenAmount() - amt);
        credit.setUpdateTime(new Date());
        creditDao.updateByPrimaryKey(credit);
        return Response.success(credit);
    }

    @Override
    @Transactional
    public Response<FintechCredit> unOutfrozenCredit(String userKey, Integer amt) {
        FintechCredit credit = getByUserKey(userKey);
        if (credit.getForzenAmount() == null) {
            credit.setForzenAmount(0L);
        }
        if (credit.getForzenAmount() < amt) {
            return Response.fail("解冻失败，额度不足");
        }
        credit.setForzenAmount(credit.getForzenAmount() - amt); // 冻结金额减少
        credit.setFreezeAmount(credit.getFreezeAmount() + amt); // 已应金额增加
        credit.setUpdateTime(new Date());
        creditDao.updateByPrimaryKey(credit);
        return Response.success(credit);
    }

    @Override
    public Response<FintechCredit> recoverCredit(String userKey, Integer amt) {
//        FintechCredit credit=getByUserKey(userKey);
//        if(credit==null||amt==null){
//            return Response.fail("恢复失败");
//        }
//
//        if(credit.getFreezeAmount()==null){
//            credit.setFreezeAmount(0L);
//        }
//        credit.setFreezeAmount(credit.getFreezeAmount()-amt); // 减去使用过的
//        //credit.setCreditStatus(0);
//        credit.setUpdateTime(new Date());
//        creditDao.updateByPrimaryKey(credit);
        return Response.success();
    }

    private FintechCredit getByUserKey(String userKey) {
        FintechCreditExample example = new FintechCreditExample();
        example.createCriteria().andUserKeyEqualTo(userKey);
        List<FintechCredit> creditList = creditDao.selectByExample(example);
        if (creditList.size() <= 0) {
            return null;
        }
        return creditList.get(0);
    }


    @Override
    public Response editCredit(UserApprovalVO vo) {
        FintechCredit credit = getByUserKey(vo.getUserKey());
        if (credit == null) {
            return Response.fail("额度不存在");
        }
        Integer creditAmt = vo.getCreditTotalAmt() * 100;
        if (creditAmt < (credit.getForzenAmount() + credit.getFreezeAmount())) {
            return Response.fail("总额度偏小");
        }
        credit.setCreditAmount((long) creditAmt);
        credit.setUpdateTime(new Date());
        creditDao.updateByPrimaryKey(credit);
        return Response.success();
    }

    /**
     * 清除用户信息，走的是存储过程
     */
    @Override
    public Response deleteUserInfo(String userKey) {
        FintechCredit credit = getByUserKey(userKey);
        log.error("deleteUserInfo------------");
        if (credit == null) {
            log.error("deleteUserInfo用户不存在");
            return Response.fail("用户不存在");

        }
        creditDao.cleanUserInfo(userKey);
        log.error("deleteUserInfo success");
        return Response.success();
    }

    /**
     * 复活用户，creditStatus 变为0 ，所有额度全部变为0
     */
    @Override
    public Response revertUser(String userKey) {
        FintechCredit credit = getByUserKey(userKey);
        log.error("revertUser -------------------");
        if (credit == null) {
            log.error("revertUser 用户不存在--");
            return Response.fail("用户不存在");
        }
        credit.setCreditStatus(0);
        credit.setCreditAmount(0L);
        credit.setForzenAmount(0L);
        credit.setFreezeAmount(0L);
        credit.setUpdateTime(new Date());
        creditDao.updateByPrimaryKey(credit);
        log.error("revertUser success--");
        return Response.success();
    }

    @Override
    public Response deleteOrder(String userKey, String rentOrderNumber) {
        FintechCredit credit = getByUserKey(userKey);
        log.error("deleteOrder------------");
        if (credit == null) {
            log.error("deleteUserInfo用户不存在");
            return Response.fail("用户不存在");
        }
        FintechRentOrderExample example = new FintechRentOrderExample();
        FintechRentOrderExample.Criteria criteria = example.createCriteria();
        criteria.andUserKeyEqualTo(userKey);
        criteria.andRentOrderNoEqualTo(rentOrderNumber);
        List<FintechRentOrder> orderList = orderRepository.selectByExample(example);

        if (orderList == null || orderList.size() < 1) {
            log.error("订单不存在");
            return Response.fail("订单不存在");
        }
        creditDao.deleteOrder(userKey, rentOrderNumber);
        return Response.success();
    }
}
